#include <unistd.h>

#include <NVMeCommon.hpp>
#include <NVMeInfo.hpp>
#include <Utils.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>

static constexpr const char* sensorPathPrefix =
    "/xyz/openbmc_project/sensors/nvmeinfo/";
static constexpr const char* versionInterface =
    "xyz.openbmc_project.Software.Version";
static constexpr const char* sensorInterface =
    "xyz.openbmc_project.Inventory.Decorator.Asset";

//<dbus上的name>
static boost::container::flat_map<std::string, std::string> propertyNamesMap = {
    {"Manufacturer", ""}, {"FwVersion", ""},     {"SerialNumber", ""},
    {"ModuleNumber", ""}, {"InterfaceType", ""}, {"MediaType", ""},
};

NVMeInfo::NVMeInfo(sdbusplus::asio::object_server& objectServer,
                   std::shared_ptr<sdbusplus::asio::connection>& conn,
                   const std::string& sensorName, const std::string& filePath) :
    objServer(objectServer),
    conn(conn), sensorName(sensorName), filePath(filePath)
{
    int deviceNum = getDeviceNum(sensorName);
    std::string senName = "nvme" + std::to_string(deviceNum);

    //版本信息的interface
    nvmeverInterface =
        objServer.add_interface(sensorPathPrefix + senName, versionInterface);

    std::string val = "";
    nvmeverInterface->register_property("Version", val);

    val = "xyz.openbmc_project.Software.Version.VersionPurpose.NVMe";
    nvmeverInterface->register_property("Purpose", val);
    nvmeverInterface->register_property("DeviceNum", deviceNum);
    nvmeverInterface->initialize();

    // nvme静态信息的interface
    nvmeinfoInterface =
        objServer.add_interface(sensorPathPrefix + senName, sensorInterface);
    for (const auto& propertyName : propertyNamesMap)
    {
        nvmeinfoInterface->register_property(propertyName.first,
                                             propertyName.second);
    }
    nvmeinfoInterface->initialize();

    std::shared_ptr<sdbusplus::asio::dbus_interface> association =
        objectServer.add_interface(sensorPathPrefix + senName,
                                   association::interface);
    createInventoryAssoc(conn, association, sensorPathPrefix + senName);
}

void NVMeInfo::updateNVMeInfo(bool basicNVMeInfoState, bool vpdNVMeInfoState,
                              NVMeData* nvmeData)
{
    if (nvmeData == nullptr)
    {
        return;
    }

    if (basicNVMeInfoState == false)
    {
        nvmeinfoInterface->set_property("InterfaceType",
                                        nvmeData->interfaceType);
        nvmeinfoInterface->set_property("MediaType", nvmeData->mediaType);
        nvmeinfoInterface->set_property("Manufacturer", nvmeData->vendor);
        nvmeinfoInterface->set_property("FwVersion", nvmeData->firmwareVersion);
        nvmeinfoInterface->set_property("SerialNumber", nvmeData->serialNumber);
        nvmeverInterface->set_property("Version", nvmeData->firmwareVersion);
    }
    if (vpdNVMeInfoState == false)
    {
        nvmeinfoInterface->set_property("InterfaceType",
                                        nvmeData->interfaceType);
        nvmeinfoInterface->set_property("MediaType", nvmeData->mediaType);
        nvmeinfoInterface->set_property("ModuleNumber", nvmeData->modelNumber);
    }
}
